package com.example.springboot4.system.web.controller;

import cn.hutool.http.HttpStatus;
import com.example.springboot4.system.constant.RedisConstants;
import com.example.springboot4.system.exception.ServiceException;
import com.example.springboot4.system.model.LoginBody;
import com.example.springboot4.system.model.LoginUser;
import com.example.springboot4.system.model.Result;
import com.example.springboot4.system.security.handle.AuthenticationContextHolder;
import com.example.springboot4.system.security.jwt.JwtTokenUtils;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 系统登录实现
 *
 * @author 宋义州
 * @since 2024-01-10 15:59
 */
@Slf4j
@Tag(name = "系统登录")
@RestController
@RequestMapping("/api/system")
public class LoginController {

    @Resource
    private JwtTokenUtils jwtTokenUtils;

    @Resource
    private AuthenticationManager authenticationManager;

    /**
     * web用户登录
     *
     * @param params 请求参数
     * @return 最终返回信息
     */
    @Operation(summary = "登录", description = "用户登录")
    @io.swagger.v3.oas.annotations.parameters.RequestBody(description = "登录信息", content = @Content(mediaType = "application/json", schema = @Schema(implementation = LoginBody.class)))
    @ApiResponse(responseCode = "200", description = "操作成功!", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Result.class)))
    @PostMapping("/login")
    public Result<?> loginByPassword(@RequestBody LoginBody params) {
        String username = params.getAccount();
        String password = params.getPassword();
        if (StringUtils.isBlank(username) || StringUtils.isBlank(password)) {
            throw new ServiceException(HttpStatus.HTTP_BAD_REQUEST, "账号或密码为空!");
        }
        // 用户验证
        Authentication authentication;
        try {
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
            AuthenticationContextHolder.setContext(authenticationToken);
            // 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
            authentication = authenticationManager.authenticate(authenticationToken);
        } catch (Exception e) {
            if (e instanceof BadCredentialsException) {
                throw ServiceException.create(HttpStatus.HTTP_BAD_REQUEST, "账号密码不匹配!");
            } else {
                throw new ServiceException(HttpStatus.HTTP_INTERNAL_ERROR, e.getMessage());
            }
        } finally {
            AuthenticationContextHolder.clearContext();
        }

        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        // 生成token
        String token = jwtTokenUtils.createToken(loginUser);
        return Result.success(RedisConstants.TOKEN_PREFIX + token);
    }


}
